
#include "BSON.h"

#include "TestHeader.h"
#include "TestDriver.h"
#include "Logger.h"

namespace
{
  BSON::CArray* PutArrayInDocumentL(BSON::CDocument& aDoc, const TDesC& aName)
  {
    BSON::CArray* array = BSON::CArray::NewLC();
    aDoc.AppendL(aName, array);
    CleanupStack::Pop(array);
    return array;
  }
}

void CSerializationTest::testEmptyDocument()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);
  _LIT8(KBinaryEmptyDoc, "\x05\x0\x0\x0\x0");
  HBufC8* doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryEmptyDoc());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithNull()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);
  _LIT8(KBinaryNull, "\x0b\x00\x00\x00\nnull\x00\x00");
  document->AppendL(_L("null"));
  HBufC8* doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryNull());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithBool()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);
  //using replaced b with _ in name break hex-string in literal.
  _LIT8(KBinaryTrue, "\x0c\x00\x00\x00\x08_ool\x00\x01\x00");
  _LIT8(KBinaryFalse, "\x0c\x00\x00\x00\x08_ool\x00\x00\x00");
  document->AppendL(_L("_ool"), true);
  HBufC8* doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryTrue());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();

  document->AppendL(_L("_ool"), false);
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryFalse());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithInt32()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);
  _LIT8(KBinaryZero32, "\x10\x00\x00\x00\x10int32\x00\x00\x00\x00\x00\x00");
  document->AppendL(_L("int32"), 0);
  HBufC8* doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryZero32());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();
  _LIT8(KBinaryMinusOne32, "\x10\x00\x00\x00\x10int32\x00\xff\xff\xff\xff\x00");
  document->AppendL(_L("int32"), -1);
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryMinusOne32());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();
  _LIT8(KBinaryComplimentaryToOne32, "\x10\x00\x00\x00\x10int32\x00\xfe\xff\xff\xff\x00");
  document->AppendL(_L("int32"), ~1);
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryComplimentaryToOne32());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithInt64()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);
  _LIT8(KBinaryZero64, "\x14\x00\x00\x00\x12int64\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
  document->AppendL(_L("int64"), TInt64(0));
  HBufC8* doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryZero64());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();

  _LIT8(KBinaryMinusOne64, "\x14\x00\x00\x00\x12int64\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00");
  document->AppendL(_L("int64"), TInt64(-1));
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryMinusOne64());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();

  _LIT8(KBinaryComplimentaryToOne64, "\x14\x00\x00\x00\x12int64\x00\xfe\xff\xff\xff\xff\xff\xff\xff\x00");
  document->AppendL(_L("int64"), TInt64(~1));
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinaryComplimentaryToOne64());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithDouble()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  document->AppendL(_L("_ouble"), TReal64(0));
  HBufC8* doc = document->SerializeLC();
  _LIT8(KDouble0, "\x15\x00\x00\x00\x01_ouble\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KDouble0());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();

  document->AppendL(_L("_ouble"), TReal64(1));
  _LIT8(KDouble1, "\x15\x00\x00\x00\x01_ouble\x00\x00\x00\x00\x00\x00\x00\xf0?\x00");
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KDouble1());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();

  document->AppendL(_L("_ouble"), TReal64(-1));
  _LIT8(KDoubleMinusOne, "\x15\x00\x00\x00\x01_ouble\x00\x00\x00\x00\x00\x00\x00\xf0\xbf\x00");
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KDoubleMinusOne());
  CleanupStack::PopAndDestroy(doc);
  document->Reset();

  document->AppendL(_L("_ouble"), 1 / TReal64(3));
  _LIT8(KDoubleOneThird, "\x15\x00\x00\x00\x01_ouble\x00UUUUUU\xd5?\x00");
  doc = document->SerializeLC();
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KDoubleOneThird());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithUtcDateTime()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  document->AppendL(_L("utctimestamp"), TDateTime(2011, EAugust, 0, 21, 26, 30,
      123456));
  HBufC8* doc = document->SerializeLC();
  _LIT8(KUtcDateTime, "\x1b\x00\x00\x00\tutctimestamp\x00\xeb\xa7=\x87\x31\x01\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KUtcDateTime());

  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithUtfString()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  document->AppendL(_L("utfstring"), _L("value of utf string"));
  HBufC8* doc = document->SerializeLC();
  _LIT8(KDocWithUtfString, "(\x00\x00\x00\x02utfstring\x00\x14\x00\x00\x00value of utf string\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KDocWithUtfString());

  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithBinary()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  document->AppendL(
      _L("_inary"),
      _L8("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\xff"),
      BSON::CBinary::EGeneric);
  HBufC8* doc = document->SerializeLC();
  _LIT8(KBinary, "$\x00\x00\x00\x07_inary\x00\x12\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\xff\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBinary());

  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithEmptyArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"));
  HBufC8* doc = document->SerializeLC();
  _LIT8(KEmptyArray, "\x11\x00\x00\x00\x04_rray\x00\x05\x00\x00\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KEmptyArray);
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithNullInArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL();
  HBufC8* doc = document->SerializeLC();
  _LIT8(KNullInArray, "\x14\x00\x00\x00\x04_rray\x00\x08\x00\x00\x00\n0\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KNullInArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithBoolInArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL(true);
  HBufC8* doc = document->SerializeLC();
  _LIT8(KBoolInArray, "\x15\x00\x00\x00\x04_rray\x00\t\x00\x00\x00\x08"
      "0\x00\x01\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBoolInArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithInt32InArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL(true);
  HBufC8* doc = document->SerializeLC();
  _LIT8(KInt32InArray, "\x18\x00\x00\x00\x04_rray\x00\x0c\x00\x00\x00\x10\x30\x00\xff\xff\xff\xff\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KInt32InArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithInt64InArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL(TInt64(-1));
  HBufC8* doc = document->SerializeLC();
  _LIT8(KInt64inArray, "\x1c\x00\x00\x00\x04_rray\x00\x10\x00\x00\x00\x12\x30\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KInt64inArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithDoubleInArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL(TReal(1) / 3);
  HBufC8* doc = document->SerializeLC();
  _LIT8(KDoubleInArray, "\x1c\x00\x00\x00\x04_rray\x00\x10\x00\x00\x00\x01\x30\x00UUUUUU\xd5?\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KDoubleInArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithUtcDateTimeInArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL(TDateTime(2011, EAugust,
      0, 21, 26, 30, 123456));
  HBufC8* doc = document->SerializeLC();
  _LIT8(KUtcDateTimeInArray, "\x1c\x00\x00\x00\x04_rray\x00\x10\x00\x00\x00\t0\x00\xeb\xa7=\x87\x31\x01\x00\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KUtcDateTimeInArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithUtfStringInArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL(_L("string"));
  HBufC8* doc = document->SerializeLC();
  _LIT8(KUtfStringInArray, "\x1f\x00\x00\x00\x04_rray\x00\x13\x00\x00\x00\x02\x30\x00\x07\x00\x00\x00string\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KUtfStringInArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testDocumentWithEmptyArrayInArray()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  PutArrayInDocumentL(*document, _L("_rray"))->AppendL(BSON::CArray::NewLC());
  CleanupStack::Pop();
  HBufC8* doc = document->SerializeLC();
  _LIT8(KEmptyArrayinArray, "\x19\x00\x00\x00\x04_rray\x00\r\x00\x00\x00\x04\x30\x00\x05\x00\x00\x00\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KEmptyArrayinArray());
  CleanupStack::PopAndDestroy(2, document);
}

void CSerializationTest::testBsonAwesome()
{
  BSON::CDocument* document = BSON::CDocument::NewL();
  CleanupStack::PushL(document);

  BSON::CArray* array = BSON::CArray::NewLC();
  array->AppendL(_L("_wesome"));
  array->AppendL(5.05);
  array->AppendL(1986);
  document->AppendL(_L("_SON"), array);
  CleanupStack::Pop(array);

  HBufC8* doc = document->SerializeLC();
  _LIT8(KBsonAwesome, "1\x00\x00\x00\x04_SON\x00&\x00\x00\x00\x02\x30\x00\x08\x00\x00\x00_wesome\x00\x01\x31\x00\x21\x21\x21\x14@\x10\x32\x00\xc2\x07\x00\x00\x00\x00");
  TS_ASSERT_EQUALS_DESCRIPTOR(*doc, KBsonAwesome());
  CleanupStack::PopAndDestroy(2, document);
}


